package com.audaque.springboot.foshanupload.web.advice;

import com.audaque.springboot.foshanupload.core.constants.ComConst;
import com.audaque.springboot.foshanupload.core.properties.SwitchProperties;
import com.audaque.springboot.foshanupload.core.result.R;
import com.audaque.springboot.foshanupload.web.properties.IgnoreResourcePathProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.List;

/**
 * @author zgb
 * @desc ...
 * @date 2022-11-30 13:55:58
 */
@Slf4j
@ControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;

    @Value("${applicationContextPath}")
    private String applicationContextPath;

    @Autowired
    private SwitchProperties switchProperties;

    @Autowired
    private IgnoreResourcePathProperties ignoreResourcePathProperties;


    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();


        //不再使用注解局部控制，使用属性全局控制
        return true;
        /*
                RAnno rAnno = (RAnno) request.getAttribute(WebConst.R_ANNO);
        //注解不存
        if (rAnno == null) {
            return false;
        } else {
            return !returnType.getGenericParameterType().equals(R.class);
        }
*/

    }

    /**
     * supports返回true则执行该方法
     */
    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {
        //跨域
        response.getHeaders().set("Access-Control-Allow-Origin", "*");


        //Feign请求时通过拦截器设置请求头，如果是Feign请求则直接返回实体对象
        boolean isFeign = request.getHeaders().containsKey(ComConst.FEIGN_REQUEST_ID_KEY);
        Boolean returnR = switchProperties.getReturnR();
        if (isFeign) {
            return data;
        }
        URI uri = request.getURI();
        String url = uri.toString();
        log.debug("url：" + url);

        String path = uri.getPath();
        log.debug("path：" + path);

        String pathResource = path.replaceFirst(applicationContextPath, "");
        log.debug("pathResource：" + pathResource);


        PathMatcher pathMatcher = new AntPathMatcher();
        List<String> list = ignoreResourcePathProperties.getList();

        for (String s : list) {
            if (pathMatcher.match(s, pathResource)) {
                return data;
            }
        }
        if (returnR) {
            if (data instanceof String || returnType.getGenericParameterType().equals(String.class)) {
                return objectMapper.writeValueAsString(new R<>(data));
            } else if (data instanceof R) {
                return data;
            } else {
                return new R<>(data);
            }
        } else {
            return data;
        }


    }

}
